﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Xml;
using System.Text.RegularExpressions;
using System.IO;
using System.Text;

namespace SST.WebClient.Util
{
    /// <summary>
    /// Helper functions
    /// </summary>
    internal class Helper
    {
        #region Download webpage
        public event EventHandler<HelperDownloadWebpageEventArgs> DownloadWebpageAsyncCompleted;

        /// <summary>
        /// Just download webpage from url using ISO-8859-1 encoding
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public void DownloadWebpageAsync(string url)
        {
            DownloadWebpageAsync(url, "ISO-8859-1");
        }

        /// <summary>
        /// Just download webpage from url
        /// </summary>
        /// <param name="url"></param>
        /// <param name="encoding">For request and response together</param>
        /// <returns></returns>
        public void DownloadWebpageAsync(string url, string encoding)
        {
            Debug("url=" + url);
            System.Net.WebClient client = new System.Net.WebClient();
            client.Headers["User-Agent"] = "Mozilla/5.0 (compatible; MSIE 9.0;";
            client.Headers["Accept"] = "text/html, application/xhtml+xml,*/*";
            client.Headers["HTTP_ACCEPT_LANGUAGE"] = "en-US";
            client.Headers["Accept-Language"] = "en-US";
            client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
            client.Encoding = Encoding.GetEncoding(encoding);
            client.DownloadStringAsync(new Uri(url));
        }

        void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                //fire event to return null
                Debug(e.Error);
                OnDownloadWebpageAsyncCompleted(new HelperDownloadWebpageEventArgs(null));
                return;
            }
            else
            {
                try
                {
                    Debug(e.Result);
                    OnDownloadWebpageAsyncCompleted(new HelperDownloadWebpageEventArgs(e.Result));
                }
                catch (Exception ex)
                {
                    Debug(ex.Message + ex.StackTrace);
                }
            }
        }

        // Wrap event invocations inside a protected virtual method
        // to allow derived classes to override the event invocation behavior
        protected virtual void OnDownloadWebpageAsyncCompleted(HelperDownloadWebpageEventArgs e)
        {
            // Make a temporary copy of the event to avoid possibility of
            // a race condition if the last subscriber unsubscribes
            // immediately after the null check and before the event is raised.
            EventHandler<HelperDownloadWebpageEventArgs> handler = DownloadWebpageAsyncCompleted;

            // Event will be null if there are no subscribers
            if (handler != null)
            {
                // Use the () operator to raise the event.
                handler(this, e);
            }
        }
        #endregion

        #region Debugger
        public static void Debug(string message)
        {
            System.Diagnostics.Debug.WriteLine(message);
        }
        public static void Debug(Exception ex)
        {
            Debug(ex.Message + "\r\n" + ex.StackTrace);
        }
        public static void Debug(string message, Exception ex)
        {
            Debug(message + "=>" + ex.Message + "\r\n" + ex.StackTrace);
        }
        #endregion

        /// <summary>
        /// http://www.dotnetperls.com/remove-html-tags
        /// </summary>
        public static Regex htmlRegex = new Regex("<.*?>", RegexOptions.Compiled);
        /// <summary>
        /// Remove HTML from string with compiled Regex.
        /// </summary>
        public static string StripTagsRegexCompiled(string source)
        {
            return htmlRegex.Replace(source, string.Empty);
        }



        /// <summary>
        /// Forward search for given rgx till end
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="rgx"></param>
        /// <returns>Null if failed</returns>
        public static Match ForwardMatch(StringReader reader, Regex rgx)
        {
            do
            {
                string tmp = reader.ReadLine();
                if (tmp == null)
                    break;

                Match m = rgx.Match(tmp);
                if (m.Success)
                    return m;
            } while (reader.Peek() != -1);
            return null;
        }


        public static void PostToWeb(Uri uri, byte[] data, bool isMethodPost, CookieCollection cookie, Action<string, CookieCollection> callback)
        {
            var request = (HttpWebRequest)WebRequest.Create(uri);
            //http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetrequeststream.aspx

            CookieContainer requestCookies = new CookieContainer();
            if (cookie != null)
                requestCookies.Add(uri, cookie);
            request.CookieContainer = requestCookies;

            if (isMethodPost)
            {
                request.Method = "post";
                request.ContentType = "application/x-www-form-urlencoded";

                // start the asynchronous operation
                request.BeginGetRequestStream((asynchronousResult) =>
                {
                    try
                    {
                        using (Stream postStream = request.EndGetRequestStream(asynchronousResult))
                        {
                            postStream.Write(data, 0, data.Length);
                            postStream.Close();
                        }

                        // Start the asynchronous operation to get the response
                        request.BeginGetResponse((asynchronousResponseResult) =>
                        {
                            try
                            {
                                string responseString = null;
                                using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResponseResult))
                                {
                                    using (Stream responseStream = response.GetResponseStream())
                                    {
                                        StreamReader streamRead = new StreamReader(responseStream);
                                        responseString = streamRead.ReadToEnd();

                                        responseStream.Close();
                                    }
                                    response.Close();
                                }
                                Helper.Debug("responseString=" + responseString);

                                if (callback != null)
                                    callback(responseString, request.CookieContainer != null ? request.CookieContainer.GetCookies(request.RequestUri) : null);
                                return;
                            }
                            catch (Exception ex)
                            {
                                Helper.Debug(ex);
                            }
                            if (callback != null)
                                callback(null, null);
                        }, request);
                    }
                    catch (Exception ex)
                    {
                        Helper.Debug(ex);
                        if (callback != null)
                            callback(null, null);
                    }
                }, request);
            }
            else
            {
                request.BeginGetResponse((asynchronousResponseResult) =>
                {
                    try
                    {
                        string responseString = null;
                        using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResponseResult))
                        {
                            using (Stream responseStream = response.GetResponseStream())
                            {
                                StreamReader streamRead = new StreamReader(responseStream);
                                responseString = streamRead.ReadToEnd();

                                responseStream.Close();
                            }
                            response.Close();
                        }
                        Helper.Debug("responseString=" + responseString);

                        if (callback != null)
                            callback(responseString, request.CookieContainer != null ? request.CookieContainer.GetCookies(request.RequestUri) : null);
                        return;
                    }
                    catch (Exception ex)
                    {
                        Helper.Debug(ex);
                    }
                    if (callback != null)
                        callback(null, null);
                }, request);
            }
        }
    }

    /// <summary>
    /// Contains downloaded html
    /// </summary>
    public class HelperDownloadWebpageEventArgs : EventArgs
    {
        private string _html;

        public string Html
        {
            get { return _html; }
            set { _html = value; }
        }

        public HelperDownloadWebpageEventArgs (string html)
        {
            this._html = html;
        }
    }
}
